package com.cloudbroker.bcs.platform.ltb.common.util;

import com.cloudbroker.bcs.common.constants.FileType;
import com.cloudbroker.bcs.common.util.IOUtil;
import com.cloudbroker.bcs.common.util.ValueUtil;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.UUID;

/**
 * Created by xuyn15828 on 2016/3/31.
 */
public class CompressUtil {
    private static final Logger logger = LoggerFactory.getLogger(CompressUtil.class);
    private static final Integer KB_30 = 30 * 1024;
    private static final Double STANDARD_LEN = 1000.0;

    public static byte[] compress(InputStream ips,Long fileSize,String suffix,String type,String classpath) {
        if( type.equals("img") ) {
            if( suffix.equalsIgnoreCase(FileType.GIF.getSuffix().toString()) ) {
                return compressGif(ips, classpath, suffix, fileSize);
            } else {
                return compressImg(ips, classpath, suffix, fileSize , false);
            }
        }
        return IOUtil.streamToBytes(IOUtil.reset(ips));
    }

    public static byte[] compressGif(InputStream ips,String classpath,String suffix,Long fileSize) {
        String[] pic = null;
        String uuid = UUID.randomUUID().toString().replace("-" , "");
        String filename = classpath + uuid;
        try {
            pic = ImageSpek.splitGif(IOUtil.reset(ips) , IOUtil.ensureDir(classpath , "conf/" ,"tmp/"));
            BufferedImage[] images = new BufferedImage[pic.length];
            for (int i = 0; i < pic.length; i++) {
                images[i] = IOUtil.bytesToBufferedImage(compressImg(IOUtil.mark(IOUtil.fileToStream(new File(pic[i]))), classpath, "jpg", null , true));
            }
            ImageSpek.jpgToGif(images, filename);
            return IOUtil.fileToBytes(new File(filename));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if( pic != null ) {
                for (String picName : pic) {
                    IOUtil.delete(new File(picName));
                }
            }
        }
        return null;
    }

    public static byte[] compressImg(InputStream ips,String classpath,String suffix,Long fileSize , boolean strict) {
        try {
            if( fileSize == null ) {
                fileSize = ValueUtil.getLong(IOUtil.streamLength(IOUtil.reset(ips)),0);
            }
            classpath = IOUtil.ensureDir(classpath , "conf/" ,"tmp/");
            byte[] b = compressImgInStreamByQuality(compressImgInStreamByDimension(ips , classpath , fileSize , suffix , strict) , classpath);
            if( b != null ) return b;
        } catch (Exception e) {
            logger.error("compress image error " , e );
        }
        return IOUtil.streamToBytes(IOUtil.reset(ips));
    }

    private static String compressImgInStreamByDimension(InputStream ips,
                   String path, Long fileSize, String suffix , boolean strict) {
        final String uuid = UUID.randomUUID().toString().replace("-", "");
        OutputStream ops = null;
        try {
            ops = new BufferedOutputStream(new FileOutputStream(path+uuid));
            if (strict || fileSize > KB_30) {             //小于30K的不做处理
                BufferedImage bufferedImage = ImageIO.read(IOUtil.reset(ips));
                int width = bufferedImage.getWidth();
                int height = bufferedImage.getHeight();
                int maxLen = width > height ? width : height;
                int minLen = width > height ? height : width;
                double radiu = 2;
                if (maxLen > STANDARD_LEN) {                //宽高最大数小于1000像素的忽略,不做处理
                    radiu = minLen / STANDARD_LEN;
                }
                BufferedImage image = new BufferedImage(width/=radiu, height/=radiu, BufferedImage.TYPE_INT_BGR);
                Graphics graphics = image.createGraphics();
                graphics.drawImage(bufferedImage, 0, 0, width, height, null);
                ImageIO.write(image, suffix, new File(path + uuid));
                return uuid;
            }
            IOUtil.copy(IOUtil.reset(ips) , ops , true);
        }catch (Exception e) {
            logger.error("compress image error " , e );
        } finally {
            IOUtil.flush(ops);
            IOUtil.close(ops);
        }
        return uuid;
    }


    private static byte[] compressImgInStreamByQuality(String tmpName, String path) {
        final String uuid = UUID.randomUUID().toString().replace("-" , "");
        final String filename =  path + uuid;
        File pathFile = new File(path);
        File tmpFile = new File(path + tmpName);
        InputStream ips = null;
        try {
            Thumbnails.of(tmpFile).scale(1f).outputQuality(0.25f).toFile(filename);
            //tmpFile.delete();
            tmpFile = IOUtil.findFile(pathFile , new FileFilter() {
                public boolean accept(File pathname) {
                    return pathname.getName().startsWith(uuid);
                }
            });
            ips = IOUtil.mark(new FileInputStream(tmpFile));
            return IOUtil.streamToBytes(ips);
        } catch (Exception e) {
            logger.error("compress image error " , e );
        } finally {
            IOUtil.close(ips);
            tmpFile.delete();
        }
        return null;
    }
}
